import classNames from 'classnames';
import React, { Fragment } from 'react';
import ReactDOM from 'react-dom';

import { getPageBoundingClientRect } from '../../utils/utility';
import { DropdownPopup } from './DropdownPopup';

export interface IDropdownProps {
  open: boolean;
  dropdownKey?: string;
  controller: React.ReactElement<any>;
  onDismiss?: () => void;
  children: React.ComponentType;
  popupClassName?: string;
}

interface IDropdownState {
  top: number;
  left: number;
}

export class Dropdown extends React.Component<IDropdownProps, IDropdownState> {
  public controller?: HTMLElement;
  public dropdown = React.createRef<DropdownPopup>();

  constructor(props: IDropdownProps) {
    super(props);
    this.state = { top: 0, left: 0 };
    this.triggerDismiss = this.triggerDismiss.bind(this);
  }

  public componentDidMount() {
    this.saveDom();
    document.addEventListener('click', this.triggerDismiss);
    if (this.props.open) {
      // 尚未挂载时，默认位置为（0,0），可能导致错位
      this.forceUpdate();
    }
  }

  public componentWillUnmount() {
    document.removeEventListener('click', this.triggerDismiss);
  }

  public componentDidUpdate() {
    this.saveDom();
  }

  public triggerDismiss(event: MouseEvent) {
    if (!this.props.onDismiss) {
      return;
    }
    let currentEle = event.srcElement;
    while (currentEle) {
      const dropdownEle = this.dropdown.current && this.dropdown.current.ele;
      if (currentEle === this.controller || (dropdownEle && currentEle === dropdownEle)) {
        return;
      }
      currentEle = currentEle.parentElement;
    }
    this.props.onDismiss();
  }

  public saveDom() {
    this.controller = ReactDOM.findDOMNode(this) as HTMLElement;
  }

  public getStyle() {
    if (this.controller) {
      const rect = getPageBoundingClientRect(this.controller);
      return { top: rect.bottom, left: rect.left };
    }
    return { top: 0, left: 0 };
  }

  public render() {
    const { controller, open, children, popupClassName } = this.props;
    const Child = children;
    return (
      <Fragment>
        {React.cloneElement(controller, { className: classNames(controller.props.className, 'dropdown__controller') })}
        <DropdownPopup
          ref={this.dropdown}
          dropdownKey={this.props.dropdownKey}
          style={{ ...this.getStyle() }}
          open={open}
          className={popupClassName}
        >
          <Child />
        </DropdownPopup>
      </Fragment>
    );
  }
}
